
package com.scalar.chiptrack.jobs;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import com.scalar.ScalarException;

import com.scalar.chiptrack.jobs.dao.JobDAO;
import com.scalar.chiptrack.utils.Logger;
import com.scalar.chiptrack.utils.Mailer;
import com.scalar.chiptrack.utils.ConfigManager;
import com.scalar.chiptrack.adaptor.AdaptorUtils;
import com.scalar.chiptrack.adaptor.AdaptorConstants;




public abstract class JobHandler extends TimerTask  implements AdaptorConstants {

    protected String p_name = null;
    protected String p_status = Job.STATUS_NEW;
    protected long p_startTime = -1;
    protected long p_totalExecutionTime = -1;
    protected Job p_job = null;
    private Logger p_handlerLogger = null;

    protected JobHandler() {
        p_name = this.getClass().getName(); // default name
        try {
            p_handlerLogger = AdaptorUtils.getJobHandlerLogger();
        }
        catch (ScalarException se) {
            System.out.println ("ERROR!! ERROR!! ERROR!! Could not create get the logger to log Job Handler activity, Exception: " + se);
        }
    }

    protected JobHandler (String name) {
        p_name = name;
        try {
            p_handlerLogger = AdaptorUtils.getJobHandlerLogger();
        }
        catch (ScalarException se) {
            System.out.println ("ERROR!! ERROR!! ERROR!! Could not create get the logger to log Job Handler activity, Exception: " + se);
        }
    }

    // added....

    private Timer m_timer = null;


    // added....
    public  void  jobAddToTimer(long starttime) {

        m_timer = new Timer();
        m_timer.schedule(this,starttime);

    }
    public  void  jobAddToTimer(java.util.Date starttime) {

        m_timer = new Timer();
        m_timer.schedule(this,starttime);
    }

    public void run() {

        String from;
        String to;
        String message;
        String subject;
        String warning = "";


        p_startTime = System.currentTimeMillis();
	    System.out.println ("\nJob Handler: " + p_name + " - started at " + new Date (p_startTime));

	    p_status = Job.STATUS_RUNNING;

        boolean dbUpdated = false;
        try {

            // update this job in the database with status and start time
            p_job.setStartTime(new Date(System.currentTimeMillis()));
            p_job.setStatus (p_status);

            int statusId = JobDAO.insertJobStatusByJobHandler (p_job.getId(), p_job.getHandler(), p_job.getStatus(), p_job.getStartTime());
            p_job.setStatusId (statusId);

            dbUpdated = true;
        }
        catch (ScalarException se) {
            System.out.println ("Job Handler: Could not update job state in the database, job not executed...");
            System.out.println ("Job Handler: Job name = " + p_job.getName() + ", status = " + p_status + ", start time = " + p_job.getStartTime());
            se.printStackTrace();
        }

        if (dbUpdated == false) {
            return;
        }


        //////////////// do actual processing /////////////
        try {
            execute();
        }
        catch (Exception e) {
            p_status = Job.STATUS_FAILED;
            log ("\n\n+-----------Exception in Job Handler on " + new java.util.Date (System.currentTimeMillis()) + " -------------+\n" +
                 "for the job " + p_name +
                 "+ \n" +   e +  "+---------------------------------------------------------------+\n");
            System.out.println("Exception while running the job"+ p_name + ":\n"+ e );
            if ( e.toString() != null )
            {
                warning = e.toString();
            }

            StringBuffer sb = new StringBuffer();
            if ( e != null )
            {
                StackTraceElement stc[] = e.getStackTrace();
                if ( stc != null )
                {
                    for (int i =0; i < stc.length; i++ )
                    {
                        sb = sb.append("\n").append( stc[i].toString() );
                    }
                }
            }

            warning = warning + sb.toString();
        }
        //////////////////////////////////////////////////

        long endTime = System.currentTimeMillis();
	    p_totalExecutionTime = (endTime - p_startTime);
	    System.out.println ("\nJob Handler: " + p_name + " - done, time taken = " + p_totalExecutionTime);

        if (p_status != Job.STATUS_ABORTED && p_status != Job.STATUS_FAILED) {   // there was an abort signal raised already
            p_status = Job.STATUS_DONE;         // leave the status as it is...
        }

        try {
            // Update database

            p_job.setTimeTaken (p_totalExecutionTime);
            p_job.setStatus (p_status);

            log ("\n\n+-----------Job " + p_name + "    started Updating Job State at " + new java.util.Date (System.currentTimeMillis()) + " -------------+\n" +
                 "+---------------------------------------------------------------+\n");
            JobDAO.updateJobState (p_job.getStatusId(), p_job.getStatus(), new Date (endTime), p_job.getTimeTaken()/1000);
            log ("\n\n+-----------Job " + p_name + "    Completed Updating Job State at " + new java.util.Date (System.currentTimeMillis()) + " -------------+\n" +
                 "+---------------------------------------------------------------+\n");

            from = ConfigManager.getScalarAdminEmail();
            int index = from.lastIndexOf("\\");
            from  = from.substring( index+1, from.length() );
            to = p_job.getEmails();
            //when no emailIds found,sending mail to Admin is not required.
           /* if ( to == null || to.length() == 0 )
            {
                to = from;
            }*/
            subject = "Job " + p_name + "  " + p_status + " Notification";
            message = "Job " + p_name + "  " + p_status + " at " + new Date (endTime) +"\n";

            if ( warning !=null && warning.length() > 0 )
            {
                message = message + "\n\t\t\n" + warning;
            }

            if ( from != null && to != null && from.length() > 0 && to.length() > 0
                    && ( p_status.equalsIgnoreCase(Job.STATUS_ABORTED) ||  p_status.equalsIgnoreCase(Job.STATUS_FAILED) ) )
            {
                Mailer.send ( from, to, null, null, subject, message, null, Mailer.CONTENT_TYPE_HTML, false );
            }
            m_timer.cancel();  // added
        }
        catch (ScalarException se) {
            System.out.println ("Job Handler: Job has been executed, but Could not update job state in the database");
            System.out.println ("Job Handler: Job name = " + p_job.getName() + ", status = " + p_status + ", time taken = " + p_job.getTimeTaken());
            log ("\n\n "+ se.getMessage() +" \n\n" );
            se.printStackTrace();
        }
        catch (Exception se) {
            log ("\n\n "+ se.getMessage() +" \n\n" );
            System.out.println ("Unable to send the mail.");
        }
    }

    // To be implemented by sub classes
    public abstract void execute() throws Exception;

    public long getStartTime() {
        return p_startTime;
    }

    public long getTotalExecutionTime() {
        return p_totalExecutionTime;
    }

    public String getName() {
        return p_name;
    }
    public void setName (String name) {
        p_name = name;
    }

    public String getStatus() {
        return p_status;
    }

    public void setStatus (String status) {
        p_status = status;
    }

    public void setJob (Job job) {
        p_job = job;
    }
    public Job getJob() {
        return p_job;
    }

    public void abort() {
        cancel();
        p_status = Job.STATUS_ABORTED;

        try {
            // Update state in database
            long endTime = System.currentTimeMillis();
            p_totalExecutionTime = (endTime - p_startTime);
            p_job.setTimeTaken (p_totalExecutionTime);
            p_job.setStatus (p_status);

            JobDAO.updateJobState (p_job.getStatusId(), p_job.getStatus(), new Date (endTime), p_job.getTimeTaken()/1000);
        }
        catch (ScalarException se) {
            System.out.println ("Job Handler: Job has been aborted, but Could not update job state in the database");
            System.out.println ("Job Handler: Job name = " + p_job.getName() + ", status = " + p_status + ", time taken = " + p_job.getTimeTaken());
            se.printStackTrace();
        }
    }


    public boolean canOverlap() {
        return false;   // only one job should run at any given time instance
    }

    //added by phani 21/07/2004
    private void log (String message) {

        if (message == null) return;

        if (p_handlerLogger != null) {
            synchronized (p_handlerLogger) {
                p_handlerLogger.logDebug (message + LINE_SEPARATOR);
            }
        }
        else {
            System.out.println (message);
        }
    }

}